/*
This file is part of Jumpers.

Jumpers is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.

Jumpers is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with Jumpers.  If not, see <http://www.gnu.org/licenses/>.
*/

package org.chaoticengine.cgll.entity.component.render;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.chaoticengine.cgll.entity.component.ActiveRenderComponent;
import org.chaoticengine.cgll.entity.component.Command;
import org.newdawn.slick.GameContainer;
import org.newdawn.slick.Graphics;
import org.newdawn.slick.Image;
import org.newdawn.slick.SlickException;
import org.newdawn.slick.geom.Rectangle;
import org.newdawn.slick.geom.Vector2f;
import org.newdawn.slick.state.StateBasedGame;
import org.simpleframework.xml.Element;
import org.simpleframework.xml.ElementList;

/**
 * Component to render an entity as a multi-layered images. Layers can be
 * individually rotated.
 *
 * @author Matt v.d. Westhuizen
 */
public class LayeredImageRenderComponent extends ActiveRenderComponent {
    private List<Layer> layers = new ArrayList<Layer>();
    private Map<String, Command> commands = new HashMap<String, Command>();

    public LayeredImageRenderComponent() {
    }

    @ElementList(name="layers", entry="layer")
    public List<Layer> getLayers() {
        return(layers);
    }

    @ElementList(name="layers", entry="layer")
    public void setLayers(List<Layer> layers) {
        this.layers = layers;
    }

    @Override
    public void onSetOwner() {
        if (layers.size() == 0) {
            return;
        }

        // Get the base layer and use that to create the bounding box
        Image img = layers.get(0).image;
        if (img == null) {
            return;
        }

        // Create the bounding box
        Vector2f pos = owner.getPosition();
        owner.setBoundingRectangle(new Rectangle(pos.getX(), pos.getY(), img.getWidth(), img.getHeight()));
    }

    @Override
    public void update(GameContainer gc, StateBasedGame sb, int delta) {
        super.update(gc, sb, delta);
        
        for (int i = 0; i < this.layers.size(); i++) {
            Layer l = layers.get(i);
            if (l.getRate() != 0.0f) {
                l.setRotation(l.getRotation() + l.getRate() * (delta / 1000.0f));
            }
        }
    }

    @Override
    public void render(GameContainer gc, StateBasedGame sb, Graphics gr) {
        // Get the initial position and rotation
        Vector2f pos = new Vector2f(this.owner.getPosition());

        // Apply any translations to the position before rendering
        pos.add(this.owner.getTranslation());

        // Render all layers
        for (int i = 0; i < layers.size(); i++) {
            Image img = layers.get(i).image;
            float rat = layers.get(i).getRate();

            if (rat != 0.0f) {
                // Store initial image rotation
                float rot = img.getRotation();

                // Rotate the image
                img.setRotation(layers.get(i).rotation);

                // Render the image
                gr.drawImage(img, pos.x, pos.y);

                // Reset the image rotation as it is a shared resource
                img.setRotation(rot);
            } else { // No rotation simply render the image
                gr.drawImage(img, pos.x, pos.y);
            }
        }
    }

    @Override
    public Map<String, Command> getCommands() {
        return(commands);
    }

    public class Layer {
        protected Image image = null;
        protected float rotation = 0.0f;
        protected float rotation_rate = 0.0f;

        @Element(name="image")
        public String getImage() {
            if (image != null) {
                return(image.getResourceReference());
            } else {
                return("");
            }
        }

        @Element(name="image")
        public void setImage(String filename) {
            try {
                image = new Image(filename);
            } catch (SlickException sEx) {
                sEx.printStackTrace();
                System.out.println("Error: Problem loading image '" + filename + "'.");
            }
        }

        public float getRotation() {
            return(rotation);
        }

        public void setRotation(float f) {
            rotation = f;
        }

        @Element(name="rotation", required=false)
        public float getRate() {
            return(rotation_rate);
        }

        @Element(name="rotation", required=false)
        public void setRate(float f) {
            rotation_rate = f;
        }
    }
}
